package edu.buffalo.cse.cse486_586.simpledht.activity;

import edu.buffalo.cse.cse486_586.simpledht.R;
import edu.buffalo.cse.cse486_586.simpledht.config.Configuration;
import edu.buffalo.cse.cse486_586.simpledht.config.Node;
import edu.buffalo.cse.cse486_586.simpledht.service.NetWorkService;
import edu.buffalo.cse.cse486_586.util.AppUtil;
import android.app.Activity;
import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.database.Cursor;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;

public class MainActivity extends Activity {
	// Debugging
	private static final String TAG = "MainActivity";
	private static final boolean D = true;

	// Layout Views
	private EditText keyTxt;
	private EditText valueTxt;
	private ListView msgList;
	private Button insertButton;
	private Button dumpButton;
	private Button cleanButton;
	private Button debugButton;
	private Button addButton;
	private Button searchButton;
	private Button joinButton;

	// Array adapter for the conversation thread
	private ArrayAdapter<String> msgListAdapter;

	// incoming Messenger for communicating with service.
	final private Messenger incommingMessager = new Messenger(
			new MessagerHandler());
	// outgoing Messenger for communicating with service
	private Messenger outgoingMessager = null;
	// Flag indicating whether we have called bind on the service.
	boolean mIsBound;

	// Handler of messages from binded service.
	class MessagerHandler extends Handler {
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case AppUtil.MSG_DISABLE_BUTTON:
				disableAllButton();
				break;
			case AppUtil.MSG_ENABLE_BUTTON:
				enableAllButton();
				break;
			case AppUtil.MSG_UPDATE_VIEWLIST:
				msgListAdapter.clear();
				queryData();
				break;
			case AppUtil.MSG_RETREIVE_RESULT:
				String result = msg.getData().getString(AppUtil.RESULT);
				msgListAdapter.add(result);
				break;
			default:
				super.handleMessage(msg);
				break;
			}
		}
	}

	/**
	 * Class for interacting with the main interface of the service.
	 */
	public NetWorkConnection mConnection = new NetWorkConnection();

	class NetWorkConnection implements ServiceConnection {
		public void onServiceConnected(ComponentName className, IBinder service) {
			// This is called when the connection with the service has been
			// established, giving us the service object we can use to
			// interact with the service. We are communicating with our
			// service through an IDL interface, so get a client-side
			// representation of that from the raw service object.
			outgoingMessager = new Messenger(service);
			if (D)
				Log.d(TAG, "Attached.");

			// We want to monitor the service for as long as we are
			// connected to it.
			try {
				Message msg = Message.obtain(null, AppUtil.MSG_REGISTER_CLIENT);
				msg.replyTo = incommingMessager;
				outgoingMessager.send(msg);
			} catch (RemoteException e) {
				Log.e(TAG, "Exception", e);
			}
		}

		public void onServiceDisconnected(ComponentName className) {
			// This is called when the connection with the service has been
			// unexpectedly disconnected -- that is, its process crashed.
			outgoingMessager = null;
			if (D)
				Log.d(TAG, "detached.");
		}

		public void testCase1() {
			try {
				Message msg = Message.obtain(null, AppUtil.MSG_TEST_CASE_1);
				msg.replyTo = incommingMessager;
				outgoingMessager.send(msg);
			} catch (RemoteException e) {
				Log.e(TAG, "Exception", e);
			}
		}

		public void testCase2() {
			msgListAdapter.clear();
			queryData();
		}

		public void cleanViewList() {
			getContentResolver().delete(AppUtil.CONTENT_URI, null, null);
			msgListAdapter.clear();
		}

		public void cleanLV() {
			msgListAdapter.clear();
		}
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		// binding activity with service
		setupChatView();

		if (!mIsBound) {
			bindService(new Intent(this, NetWorkService.class), mConnection,
					Context.BIND_AUTO_CREATE);
			mIsBound = true;
		}
	}

	@Override
	public void onStart() {
		super.onStart();
	}

	/*
	 * set up UI interface once the activity start.
	 */
	private void setupChatView() {
		keyTxt = (EditText) findViewById(R.id.keyTxt);
		valueTxt = (EditText) findViewById(R.id.valueTxt);

		// message view list
		msgList = (ListView) findViewById(R.id.msgList);
		msgListAdapter = new ArrayAdapter<String>(this, R.layout.list_msg);
		try {
			queryData();
		} catch (Exception e) {
			Log.d(TAG, "Exception", e);
		}
		msgList.setAdapter(msgListAdapter);

		insertButton = (Button) findViewById(R.id.insertButton);
		insertButton.setOnClickListener(new InsertListener());
		dumpButton = (Button) findViewById(R.id.dumpButton);
		dumpButton.setOnClickListener(new DumpListener());
		cleanButton = (Button) findViewById(R.id.cleanButton);
		cleanButton.setOnClickListener(new CleanListener());
		debugButton = (Button) findViewById(R.id.debugButton);
		debugButton.setOnClickListener(new DebugListener());
		addButton = (Button) findViewById(R.id.addButton);
		addButton.setOnClickListener(new AddListener());
		searchButton = (Button) findViewById(R.id.searchButton);
		searchButton.setOnClickListener(new SearchListener());
		joinButton = (Button) findViewById(R.id.joinButton);
		joinButton.setOnClickListener(new JoinListener());

		disableAllButton();
	}

	public void disableAllButton() {
		insertButton.setEnabled(false);
		dumpButton.setEnabled(false);
		addButton.setEnabled(false);
		searchButton.setEnabled(false);
	}

	public void enableAllButton() {
		insertButton.setEnabled(true);
		dumpButton.setEnabled(true);
		addButton.setEnabled(true);
		searchButton.setEnabled(true);
	}

//	private void insertData() {
//		ContentValues cv = new ContentValues();
//		cv.put(AppUtil.KeyValueTable.COL_PROVIDER_KEY, "msg0001");
//		cv.put(AppUtil.KeyValueTable.COL_PROVIDER_VALUE, "msg content 00001");
//		getContentResolver().insert(AppUtil.CONTENT_URI, cv);
//
//		cv.put(AppUtil.KeyValueTable.COL_PROVIDER_KEY, "msg0002");
//		cv.put(AppUtil.KeyValueTable.COL_PROVIDER_VALUE, "msg content 00002");
//		getContentResolver().insert(AppUtil.CONTENT_URI, cv);
//	}

	private void queryData() {
		Cursor c = getContentResolver().query(
				AppUtil.CONTENT_URI,
				new String[] { AppUtil.KeyValueTable.COL_ID,
						AppUtil.KeyValueTable.COL_PROVIDER_KEY,
						AppUtil.KeyValueTable.COL_PROVIDER_VALUE }, null, null,
				null);

		if (c.moveToFirst()) {
			while (!c.isAfterLast()) {
				String out = "";
				out += c.getString(c
						.getColumnIndexOrThrow(AppUtil.KeyValueTable.COL_PROVIDER_KEY));
				out += " : ";
				out += c.getString(c
						.getColumnIndexOrThrow(AppUtil.KeyValueTable.COL_PROVIDER_VALUE));
				msgListAdapter.add(out);
				c.moveToNext();
			}
		}

	}

	private class InsertListener implements OnClickListener {
		@Override
		public void onClick(View v) {
			mConnection.testCase1();
		}

	}

	private class DumpListener implements OnClickListener {
		@Override
		public void onClick(View v) {
			mConnection.testCase2();
		}
	}

	private class CleanListener implements OnClickListener {
		@Override
		public void onClick(View v) {
			mConnection.cleanViewList();
		}
	}

	private class DebugListener implements OnClickListener {
		@Override
		public void onClick(View v) {
			mConnection.cleanLV();

			Node n = Configuration.getInstance().getNode();
			Log.d(TAG, "local port:" + n.getNodePort() + "//" + "predecessor:"
					+ n.getPredecessor() + "successor:" + n.getSuccessor());
		}
	}

	private class JoinListener implements OnClickListener {
		@Override
		public void onClick(View v) {
			try {
				Message msg = Message.obtain(null, AppUtil.MSG_JOIN);
				msg.replyTo = incommingMessager;
				outgoingMessager.send(msg);
			} catch (RemoteException e) {
				Log.e(TAG, "Exception", e);
			}
		}
	}

	private class AddListener implements OnClickListener {
		@Override
		public void onClick(View v) {
			String key = keyTxt.getText().toString();
			String value = valueTxt.getText().toString();

			try {
				Message msg = Message.obtain(null, AppUtil.MSG_ADD);
				android.os.Bundle b = new android.os.Bundle();
				b.putString(AppUtil.KEY, key);
				b.putString(AppUtil.VALUE, value);
				msg.setData(b);
				msg.replyTo = incommingMessager;
				outgoingMessager.send(msg);
			} catch (RemoteException e) {
				Log.e(TAG, "Exception", e);
			}
		}
	}

	private class SearchListener implements OnClickListener {
		@Override
		public void onClick(View v) {
			String key = keyTxt.getText().toString();
			try {
				Message msg = Message.obtain(null, AppUtil.MSG_RETREIVE);
				android.os.Bundle b = new android.os.Bundle();
				b.putString(AppUtil.KEY, key);
				msg.setData(b);
				msg.replyTo = incommingMessager;
				outgoingMessager.send(msg);
			} catch (RemoteException e) {
				Log.e(TAG, "Exception", e);
			}
		}
	}
}